package org.dreamwork.jasmine2.util;

import org.dreamwork.util.ICollection;

import java.util.*;
import java.util.regex.Pattern;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

/**
 * Created by IntelliJ IDEA.
 * User: seth
 * Date: 2009-2-2
 * Time: 17:32:24
 */
public class DataBinder {
    private static final Object[] args = {};
    private static final Pattern pattern = Pattern.compile ("^[\\d]+$");

    private static boolean isNumber (String string) {
        return pattern.matcher (string).matches ();
    }

    public static Iterator parseDataSource (Object dataSource, String dataMember) {
        if (dataMember != null) {
            Object obj = getValue (dataSource, dataMember);
            return parseDataSource (obj);
        } else {
            return parseDataSource (dataSource);
        }
    }

    @SuppressWarnings ("unchecked")
    public static Iterator parseDataSource (Object dataSource) {
        if (dataSource instanceof Iterator)
            return (Iterator) dataSource;
        if (dataSource instanceof Collection)
            return ((Collection) dataSource).iterator ();
        if (dataSource instanceof ICollection) {
            ArrayList list = new ArrayList ();
            ICollection c = (ICollection) dataSource;
            for (int i = 0; i < c.count (); i ++)
                list.add (c.get (i));
            return list.iterator ();
        }
        if (dataSource instanceof Object[])
            return Arrays.asList ((Object[]) dataSource).iterator ();

        return null;
    }

    public static Object getValue (Object container, String expression) {
        String[] parts = expression.split ("\\.");
        Object current = container;
        for (int i = 0; i < parts.length; i++) {
            String propName = parts[i];
            if (propName.charAt (0) == '[') {
                propName = propName.substring (1, propName.length () - 1);
                if (!isNumber (propName)) {
                    if (propName.charAt (0) == '\'' || propName.charAt (0) == '"')
                        propName = propName.substring (1, propName.length () - 1);
                    if (current instanceof Map) current = ((Map) current).get (propName);
                    else throw new IllegalArgumentException ("Unknown expression " + parts[i]);
                } else {
                    int index = Integer.parseInt (propName);
                    if (current instanceof List) current = ((List) current).get (index);
                    else if (current instanceof Object[]) current = ((Object[]) current)[index];
                    else throw new IllegalArgumentException ("Unknown expression " + parts[i]);
                }
            } else {
                if (current instanceof Map) {
                    current = ((Map) current).get (propName);
                } else {
                    try {
                        PropertyDescriptor pd = new PropertyDescriptor (propName, current.getClass ());
                        Method method = pd.getReadMethod ();
                        current = method.invoke (current, args);
                    } catch (Exception ex) {
                        throw new RuntimeException (ex);
                    }
                }
            }
        }

        return current;
    }
}